﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Sklep.Domain.Abstract;
using Sklep.Domain.Entities;
using Sklep.WebUI.Controllers;

namespace Sklep.UnitTests
{
    [TestClass]
    public class Test2
    {
        [TestMethod]
        public void IndexContainsAllProducts()
        {
            //przygotowanie tworzenie imitacji repozytorium
            var mock = new Mock<IProductRepository>();

            mock.Setup(m => m.Products).Returns(new[]
                {
                    new Product {ProductID = 1, Name = "P1"},
                    new Product {ProductID = 2, Name = "P2"},
                    new Product {ProductID = 3, Name = "P3"}
                }.AsQueryable());

            //przygotowanie - utworzenie kontrolera
            var target = new AdminController(mock.Object);

            //dzialanie
            Product[] result = ((IEnumerable<Product>) target.Index().ViewData.Model).ToArray();

            Assert.AreEqual(result.Length,3);
            Assert.AreEqual("P1",result[0].Name);
            Assert.AreEqual("P2", result[1].Name);
            Assert.AreEqual("P3", result[2].Name);
        }

        [TestMethod]
        public void CanEditProduct()
        {
            //przygotowanie - tworzenie imitacji repozytorium
            var mock = new Mock<IProductRepository>();
            mock.Setup(m => m.Products).Returns(new[]
                {
                    new Product {ProductID = 1, Name = "P1"},
                    new Product {ProductID = 2, Name = "P2"},
                    new Product {ProductID = 3, Name = "P3"}
                }.AsQueryable());

            //przygotowanie Utworzenie kontrolera
            var target = new AdminController(mock.Object);

            //dzialanie
            var p1 = target.Edit(1).ViewData.Model as Product;
            var p2 = target.Edit(2).ViewData.Model as Product;
            var p3 = target.Edit(3).ViewData.Model as Product;


            if (p1 != null) Assert.AreEqual(1,p1.ProductID);
            if (p2 != null) Assert.AreEqual(2,p2.ProductID);
            if (p3 != null) Assert.AreEqual(3,p3.ProductID);
        }

        [TestMethod]
        public void CannotEditNonExistentProduct()
        {
            //przygotowanie - Tworzenie imitacji repozytorium
            Mock<IProductRepository> mock = new Mock<IProductRepository>();
            mock.Setup(m => m.Products).Returns(new[]
                {
                    new Product {ProductID = 1, Name = "P1"},
                    new Product {ProductID = 2, Name = "P2"},
                    new Product {ProductID = 3, Name = "P3"}
                }.AsQueryable());

            //przygotowanie Tworzenie Kontrolera
            AdminController target = new AdminController(mock.Object);

            //dzialanie
            Product result = (Product) target.Edit(4).ViewData.Model;

            //asercje
            Assert.IsNull(result);
        }
        [TestMethod]
        public void CanSaveValidChanges()
        {
            //przygotowanie - tworzenie imitacji repozytorium
            Mock<IProductRepository> mock = new Mock<IProductRepository>();
            
            //przygotowanie - tworzenie kontrolera
            AdminController target = new AdminController(mock.Object);
            //przygotowanie - tworzenie produktu
            Product product = new Product {Name = "Test"};

            //dzialanie proba zapisania produktu
            //ActionResult result = target.Edit(product);

            mock.Verify(m=>m.SaveProduct(product));

            //asercje sprawdzanie typu zwracanego z metody
            //Assert.IsNotInstanceOfType(result,typeof(ViewResult));
        }

        [TestMethod]
        public void CannotSaveInvalidChanges()
        {
            //przygotowanie - tworzenie imitacji repozytorium
            Mock<IProductRepository> mock = new Mock<IProductRepository>();

            AdminController target = new AdminController(mock.Object);

            //przygotowanie - tworzenie produktu
            Product product = new Product {Name = "Test"};

            //przygotowanie dodanie bledu do modelu
            target.ModelState.AddModelError("error","error");

            //dzialanie - proba zapisania prduktu
            //ActionResult result = target.Edit(product);

            //asercje sprawdzanie czy zostalo wywolane repozytorium
            mock.Verify(m=>m.SaveProduct(It.IsAny<Product>()),Times.Never());

            //Asercje sprawdzanie typu zwracanego z metody
            //Assert.IsInstanceOfType(result,typeof(ViewResult));

        }
    }
}
